Skip to content

bundle: record auto-migration compatibility telemetry on deploy#5439

Open
shreyas-goenka wants to merge 1 commit into
mainfrom
pr-deploy-folder-permission-check
Open

bundle: record auto-migration compatibility telemetry on deploy#5439
shreyas-goenka wants to merge 1 commit into
mainfrom
pr-deploy-folder-permission-check

Conversation

@shreyas-goenka

@shreyas-goenka shreyas-goenka commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Telemetry only. Deploying a bundle requires write access (CAN_EDIT or higher) to the state folder; after an auto DMS migration that is governed by a deployment object carrying only the bundle's statically declared permissions. Migration is seamless only when everyone with write access to the state folder is declared with CAN_MANAGE — anyone missing loses the ability to deploy. Evaluated during bundle deploy by reusing the existing SetPermissions response (no extra API call).

Exactly one verdict per deploy (bool_values):

  • dms_compat_auto — all write access on the state folder is declared.
  • dms_compat_not — undeclared write access exists. Includes the statically known cases: /Workspace/Shared without users: CAN_MANAGE, and a folder under /Workspace/Users/<owner> (owner always has CAN_MANAGE) with no permissions section.
  • dms_compat_maybe — no permissions section and no known write access; resolving needs a GetPermissions call.

Plus state_path_is_shared.

Tested by one acceptance test over the location × permissions matrix, including undeclared and declared CAN_EDIT grants; the fake server models directory ACL inheritance (home owners + ancestor grants), with parent grants set up via workspace set-permissions.

@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

Commit: 4412358

Run: 27383406845

Env 🟨​KNOWN 🔄​flaky 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
🟨​ aws linux 7 15 264 972 7:53
🟨​ aws windows 7 15 266 970 17:13
💚​ aws-ucws linux 7 15 360 886 7:28
💚​ aws-ucws windows 7 15 362 884 14:17
🔄​ azure linux 2 1 17 265 970 8:54
🔄​ azure windows 2 1 17 267 968 14:31
💚​ azure-ucws linux 1 17 365 882 7:29
💚​ azure-ucws windows 1 17 367 880 14:46
💚​ gcp linux 1 17 263 973 7:56
💚​ gcp windows 1 17 265 971 11:20
24 interesting tests: 15 SKIP, 7 KNOWN, 2 flaky
Test Name aws linux aws windows aws-ucws linux aws-ucws windows azure linux azure windows azure-ucws linux azure-ucws windows gcp linux gcp windows
🟨​ TestAccept 🟨​K 🟨​K 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
🙈​ TestAccept/bundle/invariant/no_drift 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/permissions 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions 🟨​K 🟨​K 💚​R 💚​R 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=direct 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions 🟨​K 🟨​K 💚​R 💚​R 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=direct 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 🟨​K 🟨​K 💚​R 💚​R
🙈​ TestAccept/bundle/resources/postgres_branches/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/recreate 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/replace_existing 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/update_protected 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/without_branch_id 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_endpoints/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_endpoints/recreate 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_projects/update_display_name 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/synced_database_tables/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_indexes/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_indexes/grants/select 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/ssh/connection 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🔄​ TestFetchRepositoryInfoAPI_FromRepo/root ✅​p ✅​p ✅​p ✅​p 🔄​f 🔄​f ✅​p ✅​p ✅​p ✅​p
🔄​ TestFetchRepositoryInfoAPI_FromRepo/subdir ✅​p ✅​p ✅​p ✅​p 🔄​f 🔄​f ✅​p ✅​p ✅​p ✅​p
Top 28 slowest tests (at least 2 minutes):
duration env testname
6:33 azure-ucws windows TestAccept
6:08 azure windows TestAccept
6:06 gcp windows TestAccept
6:02 aws-ucws windows TestAccept
4:57 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
4:20 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
4:19 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:58 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:52 azure windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:42 aws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:22 azure windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:19 aws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:10 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:06 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:01 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:00 azure-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:59 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:57 gcp linux TestAccept
2:56 azure-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:53 azure linux TestAccept
2:47 azure-ucws linux TestAccept
2:47 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:46 aws-ucws linux TestAccept
2:45 aws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:40 aws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:32 aws-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:31 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:29 aws-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct

@shreyas-goenka shreyas-goenka force-pushed the ticklish-munching-bear branch from cc47397 to b2c7271 Compare June 5, 2026 10:05
@shreyas-goenka shreyas-goenka force-pushed the pr-deploy-folder-permission-check branch from 7c783aa to 5e587f0 Compare June 5, 2026 10:05
@shreyas-goenka shreyas-goenka force-pushed the ticklish-munching-bear branch from b2c7271 to c2aa303 Compare June 5, 2026 10:11
@shreyas-goenka shreyas-goenka force-pushed the pr-deploy-folder-permission-check branch from 5e587f0 to 2cd3ef3 Compare June 5, 2026 10:11
@shreyas-goenka shreyas-goenka force-pushed the ticklish-munching-bear branch from c2aa303 to b1d732b Compare June 5, 2026 10:14
@shreyas-goenka shreyas-goenka force-pushed the pr-deploy-folder-permission-check branch from 2cd3ef3 to 07abec1 Compare June 5, 2026 10:14
@shreyas-goenka shreyas-goenka force-pushed the ticklish-munching-bear branch from b1d732b to 9e2f26b Compare June 5, 2026 10:18
@shreyas-goenka shreyas-goenka force-pushed the pr-deploy-folder-permission-check branch from 07abec1 to 26c3380 Compare June 5, 2026 10:18
@shreyas-goenka shreyas-goenka force-pushed the ticklish-munching-bear branch from 9e2f26b to 00c5b7b Compare June 5, 2026 10:18
@shreyas-goenka shreyas-goenka force-pushed the pr-deploy-folder-permission-check branch from 26c3380 to 30172b5 Compare June 5, 2026 10:19
@shreyas-goenka shreyas-goenka force-pushed the ticklish-munching-bear branch from 00c5b7b to addcb6a Compare June 9, 2026 14:06
@shreyas-goenka shreyas-goenka force-pushed the pr-deploy-folder-permission-check branch from 30172b5 to 3646391 Compare June 9, 2026 14:06
@shreyas-goenka shreyas-goenka force-pushed the pr-deploy-folder-permission-check branch from bf9f878 to abe3dfb Compare June 10, 2026 10:42
has_serverless_compute true
local.cache.attempt true
local.cache.miss true
permissions_section_is_set false

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because permissions are not set here, by definition state_path_acl_exceeds_permissions is true.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Analysis needs to take this into account when looking at state_path_acl_exceeds_permissions.

Can we choose to not emit it when permissions are not set?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simpliefied. We only record a single is_auto_migration_compatible. All the rich logic lives in the CLI.

@shreyas-goenka shreyas-goenka changed the title bundle: warn during deploy when workspace folder permissions exceed the bundle's Warn and record when state_path folder permissions exceed static permissions block. Jun 10, 2026
@shreyas-goenka shreyas-goenka marked this pull request as ready for review June 10, 2026 10:53
@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Approval status: pending

/acceptance/bundle/ - needs approval

15 files changed
Suggested: @denik
Also eligible: @andrewnester, @pietern, @janniklasrose, @lennartkats-db, @anton-107

/bundle/ - needs approval

5 files changed
Suggested: @denik
Also eligible: @andrewnester, @pietern, @janniklasrose, @lennartkats-db, @anton-107

General files (require maintainer)

Files: libs/testserver/permissions.go
Based on git history:

  • @denik -- recent work in bundle/permissions/, libs/testserver/, bundle/metrics/

Any maintainer (@andrewnester, @anton-107, @denik, @pietern, @simonfaltum, @renaudhartert-db) can approve all areas.
See OWNERS for ownership rules.

@shreyas-goenka shreyas-goenka marked this pull request as draft June 10, 2026 11:12
@shreyas-goenka shreyas-goenka force-pushed the pr-deploy-folder-permission-check branch from abe3dfb to 3c6a454 Compare June 10, 2026 11:15
@shreyas-goenka shreyas-goenka changed the base branch from ticklish-munching-bear to main June 10, 2026 11:15
@shreyas-goenka shreyas-goenka marked this pull request as ready for review June 10, 2026 11:31
@shreyas-goenka shreyas-goenka force-pushed the pr-deploy-folder-permission-check branch from 3c6a454 to 681e089 Compare June 10, 2026 11:32
has_serverless_compute true
local.cache.attempt true
local.cache.miss true
permissions_section_is_set false

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Analysis needs to take this into account when looking at state_path_acl_exceeds_permissions.

Can we choose to not emit it when permissions are not set?

Comment thread bundle/permissions/workspace_root.go Outdated
Comment thread NEXT_CHANGELOG.md Outdated
@shreyas-goenka shreyas-goenka force-pushed the pr-deploy-folder-permission-check branch from 681e089 to e6521fb Compare June 10, 2026 12:07
@denik

denik commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

We will also track auto migration from terraform to direct, can we prefix these values with dms_ to disambiguate? I'd also use shorter names with the same prefix for grouping / easier search in telemetry dashboard.

For example, instead of
is_definitely_auto_migration_compatible
is_not_auto_migration_compatible
is_maybe_auto_migration_compatible

use:

dms_compat_auto
dms_compat_not
dms_compat_auto

Deploying a bundle requires write access (CAN_EDIT or higher) to the state folder;
after an automatic DMS migration that is governed by a deployment object carrying
only the bundle's statically declared permissions. Migration is therefore seamless
only when everyone with write access to the state folder is declared with
CAN_MANAGE in the permissions section — anyone missing loses the ability to deploy.

ApplyWorkspaceRootPermissions already calls SetPermissions on each workspace path
prefix during deploy; the response carries the folder's resulting ACL, which we
reuse (no extra API call) to evaluate this. Exactly one verdict is recorded per
deploy:
- is_definitely_auto_migration_compatible: everyone with write access to the state
  folder is statically declared.
- is_not_auto_migration_compatible: the state folder has undeclared write access.
  Includes the statically known cases: /Workspace/Shared without group_name: users
  CAN_MANAGE, and a folder under /Workspace/Users/<owner> (the owner always has
  CAN_MANAGE) with no permissions section.
- is_maybe_auto_migration_compatible: no permissions section and the state folder
  has no known write access; resolving it needs a GetPermissions call.

The fake test server now models directory ACL inheritance (home-folder owners and
ancestor folder grants appear as inherited entries), so the acceptance test
exercises the full matrix via bundle paths, declared permissions, and real parent
folder grants.

Co-authored-by: Shreyas Goenka <shreyas.goenka@databricks.com>
@shreyas-goenka

Copy link
Copy Markdown
Contributor Author

Renamed per @denik's suggestion: the three verdict keys are now dms_compat_auto / dms_compat_not / dms_compat_maybe (common dms_compat_ prefix for grouping, disambiguated from future terraform→direct migration tracking).

// not declared in perms with CAN_MANAGE, the only declarable level that grants write
// access. Read-only folder access does not need to be declared.
func (p WorkspacePathPermissions) HasUndeclaredWriters(perms []resources.Permission) bool {
for _, wp := range p.Permissions {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this different from containsAll in the function above?

I.e. does it not care about readers?

If so, we can filter out readers and then call containsAll like above to keep the logic simple.

}
return false
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a unit test for this to cover all cases and check that it matches what you need it to do.

Comment thread bundle/metrics/metrics.go
// Whether workspace.state_path is under /Workspace/Shared.
StatePathIsShared = "state_path_is_shared"

// Whether this deploy is compatible with an automatic DMS migration. Deploying a

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"DMS migration" sounds ominous (here and in the PR summary). We can be more verbose about what this is: "automatic migration to a dedicated state storage service" or something.

// giveAccessForWorkspaceRoot applies the bundle's top-level permissions to the
// workspace folders and returns the resulting permissions of the folder that holds
// the deployment state, or nil when no permissions are declared or that folder is in
// /Workspace/Shared (which is not synced).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These carve-outs make it hard to reason about this function in context.

If callers need access to any one of the folders, we can return a type with the applied permissions for each one of the paths we could care about.

For the /Shared case we can return a static permission object if we special-case it.

func setPermissions(ctx context.Context, w workspace.WorkspaceInterface, path string, permissions []workspace.WorkspaceObjectAccessControlRequest) error {
// pathContains reports whether the workspace folder at parent is, or is an ancestor
// of, child. Empty paths are treated as a match because workspace paths are fully
// defaulted before deploy. Both paths are /Workspace-normalized by PrependWorkspacePrefix.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is empty ok?

// If the folder is shared, then we don't need to set permissions since it's always set for all users and it's checked in mutators before.
if libraries.IsWorkspaceSharedPath(path) {
return nil
return nil, nil

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we return a static permission here we don't need to special case it for its callers.

if stateFolderPerms == nil {
if strings.HasPrefix(statePath, "/Workspace/Users/") {
// The home owner has CAN_MANAGE and the bundle declares no permissions.
return metrics.DMSCompatNot

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not?

A user deploying to their home directory and not specifying permissions should be compatible.

return metrics.DMSCompatNot
}
// Not under a home: we cannot tell without a GetPermissions call.
return metrics.DMSCompatMaybe

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only maybe.

We can consider making a permission check somewhere (and even bail early if we can't write) and pass it here to make a definitive verdict. Not blocking, can be a follow up.

@pietern

pietern commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

How does this take groups into account?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants